/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package aescfbencryption.encriptacion;

import aescfbencryption.basicOperations.basicOperations;
import aescfbencryption.keys.KeyGen;
import java.util.Vector;

/**
 *
 * @author JPablo
 */
public class desencriptar {

    Vector textoCifrado;
    String clave;
    String textoOriginal;
    int columnas;

    public void AES(String texto, String palabraClave){
        //Se inicializan los valores
        this.textoCifrado = new Vector();
        this.textoOriginal = "";
        this.clave = palabraClave;
        this.columnas = obtenerNumeroColumnas(clave);//Se obtiene el numero de columnas a partir de la clave


        //Se llena el texto original
        for(int i=0;i<texto.length();i++)
        {
            textoCifrado.add((int)texto.charAt(i));
        }

        int nBloques;
        //Se generan las subMatrices del texto original y se llama a encriptar(matrizTexto) con la matriz generada;
       if((textoCifrado.size()%(4*columnas))==0){
            nBloques = (textoCifrado.size()/(4*columnas));
       }else{
            nBloques = (textoCifrado.size()/(4*columnas))+1;
       }
        
        for(int i=0;i<nBloques;i++){
           int[][] matrizTexto = new int[4][columnas];
           for(int j=0; j<4;j++){
                for(int k=0;k<columnas;k++){
                    if((i*16)+(j*4)+k< textoCifrado.size()){
                        //Se llena la matriz a codificar
                        matrizTexto[j][k]= Integer.parseInt(textoCifrado.get((i*16)+(j*4)+k).toString());
                    }else{
                        matrizTexto[j][k]=20;//Se rellena con el caracter escogido
                    }
                }
           }
           desencriptar(matrizTexto);
        }
    }




    public void desencriptar(int[][] matrizTexto){

        
        //Se obtiene la Clave
        KeyGen key = new KeyGen(clave,columnas);
        key.codKeyWord();
        key.fillKeyMatrix();
        key.getAsciiKeyWord();
        key.getHexKeyWord();
        key.initFillWN();
        key.fillAllWN();
        int[][] llave = key.getW(0);
        int iter=0; // para guardar el numero de iteraciones
        
       basicOperations operacion = new basicOperations();


        //Se establece el numero de iteraciones segun el tamaño de la columna
 /*       switch(columnas)
        {
            case 4:iter=10;
            case 6:iter=12;
            default 8:iter=14;
        }*/
        /**/// UN SWITCH es mas eficiente.
        //Nose que onda no me funciono el switch..
        if(columnas==4)
            iter=10;
        if(columnas==6)
            iter=12;
        if(columnas==8)
            iter=14;


        //Primera Ronda
        //llave = key.getW(iter);// se comenta para trabajar solo con  iteraciones
        llave = key.getW(10);
        matrizTexto = operacion.AddRoundKey(matrizTexto, llave);
        matrizTexto = operacion.invShiftRow(matrizTexto);
        matrizTexto = operacion.invByteSub(matrizTexto);




       //Ronda intermedia de la 2 a la 10, 12 o 14
       // for(int i=0;i<iter;i++){//Esta funcionando solo para  iteraciones... creo que es porque no se generan mas llaves para los otros casos
        for(int i=0;i<9;i++){
            llave = key.getW(9-i); //Se obtiene la clave a utilizar
            matrizTexto = operacion.AddRoundKey(matrizTexto, llave);
            matrizTexto = operacion.invMixColumns(matrizTexto);
            matrizTexto = operacion.invShiftRow(matrizTexto);
            matrizTexto = operacion.invByteSub(matrizTexto);
        }

        //Ronda Final
        llave = key.getW(0);
        matrizTexto = operacion.AddRoundKey(matrizTexto, llave);


        // Se añade el resultado al texto codificado
        for(int i=0;i<4;i++){
            for(int j=0;j<columnas;j++){
                textoOriginal = textoOriginal + (char)matrizTexto[i][j];
            }
        }

    }





    public int obtenerNumeroColumnas(String clave){
        if(clave.length()<17)
           return 4;
        else{
            if(clave.length()<24)
               return 6;
            else
                return 8;
        }
   }


    public String getClave() {
        return clave;
    }

    public int getColumnas() {
        return columnas;
    }

    public String getTextoOriginal() {
        return textoOriginal;
    }

    public Vector getTextoCifrado() {
        return textoCifrado;
    }

    public void setClave(String clave) {
        this.clave = clave;
    }

    public void setColumnas(int columnas) {
        this.columnas = columnas;
    }

    public void setTextoOriginal(String textoOriginal) {
        this.textoOriginal = textoOriginal;
    }

    public void setTextoOriginal(Vector textoCifrado) {
        this.textoCifrado = textoCifrado;
    }

}
